<?php

namespace App\Models;

use App\Models\Observer\RecordObserver;
use App\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class MedicalRecord extends Model
{
    use SoftDeletes;

    protected $dates = ['deleted_at'];

    protected $table = 'st_medical_records';

    protected $fillable = [
        'patient_id', 'hospital_id', 'doctor_id', 'clinic_at', 'print_auxiliary',
        'medication', 'cn_medication', 'interval', 'visit_type', 'is_western', 'is_del',
    ];

    protected static function boot()
    {
        parent::boot();

        static::observe(RecordObserver::class);

        //  全局作用域
//        static::addGlobalScope('hasBindDoctor', function(Builder $builder) {
//            $builder->where('st_medical_records.doctor_id', '>', 0);
//        });
    }

    /**
     * 获取患者的上一次病历
     * @param $record_id
     * @return mixed
     *
     */
    public function previous($record_id)
    {
        $record = $this->getWithCache($record_id);

        if ($record->isFirstVisit()) {
            throw new \InvalidArgumentException('首诊查询不到上次病历！', 422);
        }

        $new = new static();
        if ($record->isChinese()) {
            $type = 'chinese';
        } else {
            $type = 'western';
        }

        return $new->where(['patient_id' => $record->patient_id])
            ->where('id', '<', $record_id)
            ->orderBy('id', 'desc')
            ->type($type)->first();
    }

    /**
     * @param \Illuminate\Database\Eloquent\Builder $builder
     * @param                                       $patient
     * @return mixed
     */
    public function scopePreviousWithPatient(Builder $builder, $patient)
    {
        if ($patient instanceof Patient) {
            $patient = $patient->id;
        }

        return $builder->where(['patient_id' => $patient])->orderBy('id', 'desc');
    }

    /**
     * @param      $record_id
     * @param bool $withTrashed
     * @return static
     */
    public function getWithCache($record_id, $withTrashed = true)
    {
        return \Cache::remember(
            $this->getTable() . ':' . $this->getKeyName() . ':' . $record_id,
            60,
            function () use ($record_id, $withTrashed) {

                $record = new static();

                if ($withTrashed) {
                    $record = $record->withTrashed();
                }

                return $record->findOrFail($record_id);
            });
    }

    /**
     * 是否首诊
     * @return bool
     */
    public function isFirstVisit()
    {
        return is_array($this->visit_type) ? $this->visit_type['key'] : $this->visit_type;
    }

    //  病历是否中医
    public function isChinese()
    {
        return !$this->isWestern();
    }

    //  病历是否西医
    public function isWestern()
    {
        return is_array($this->is_western) ? $this->is_western['key'] : $this->is_western;
    }

    /**
     * @param \Illuminate\Database\Eloquent\Builder $builder
     * @param                                       $type
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeType(Builder $builder, $type)
    {
        if ((1 == $type) || ($type == 'western')) {
            return $builder->where('is_western', 1);
        }

        if ((0 == $type) || ($type == 'chinese')) {
            return $builder->where('is_western', 0);
        }

        return $builder;
    }

    /**
     * 病历的患者信息
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function patient()
    {
        return $this->belongsTo(Patient::class);
    }

    /**
     * 病历医院
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function hospital()
    {
        return $this->belongsTo(Hospital::class);
    }

    /**
     * 看诊医生
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function doctor()
    {
        return $this->belongsTo(User::class, 'doctor_id');
    }

    /**
     * 主诉项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function complaint()
    {
        return $this->hasOne(MedicalComplaint::class, 'record_id');
    }

    public function cnDiagnose()
    {
        return $this->hasMany(CnDiagnose::class, 'record_id', 'id');
    }

    public function disease()
    {
        return $this->belongsTo(CnDiseaseDictionary::class, 'cn_disease_id')
            ->select(['id', 'name', 'icd']);
    }

    /**
     * 项病史项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function hpi()
    {
        return $this->hasOne(MedicalHpi::class, 'record_id');
    }

    /**
     * 现病史组
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function hpiSub()
    {
        return $this->hasMany(MedicalHpiSub::class);
    }

    /**
     * 既往史项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function past()
    {
        return $this->hasOne(PastHistory::class, 'record_id');
    }

    /**
     * 个人史项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function person()
    {
        return $this->hasOne(PersonalHistory::class, 'record_id');
    }

    /**
     * 月经婚育史项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function marriage()
    {
        return $this->hasOne(MarriageHistory::class, 'record_id');
    }

    /**
     * 家族史项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function family()
    {
        return $this->hasOne(FamilyHistory::class, 'record_id');
    }

    /**
     * 体格检查项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function physical()
    {
        return $this->hasOne(MedicalPhysical::class, 'record_id');
    }

    /**
     * 辅助检查
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function auxiliary()
    {
        return $this->hasOne(MedicalAuxiliary::class, 'record_id');
    }

    /**
     * 诊断项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function diagnose()
    {
        return $this->hasOne(MedicalDiagnose::class, 'record_id');
    }

    /**
     * 处理项目
     * @return \Illuminate\Database\Eloquent\Relations\HasOne
     */
    public function dispose()
    {
        return $this->hasOne(MedicalDispose::class, 'record_id');
    }

    //  获取器
    public function getPrintAuxiliaryAttribute($value)
    {
        return empty($value) ? $value : explode(',', $value);
    }

    public function getMedicationAttribute($value)
    {
        return $value ? json_decode($value, true) : [];
    }

    public function getCnMedicationAttribute($value)
    {
        return $value ? json_decode($value, true) : [];
    }

    public function getVisitTypeAttribute($value)
    {
        return ['key' => $value, 'value' => ['复诊', '首诊'][$value]];
    }

    public function getIsWesternAttribute($value)
    {
        return ['key' => $value, 'value' => ['中医', '西医'][$value]];
    }

    // 修改器
    public function setPrintAuxiliaryAttribute($value)
    {
        if (is_array($value)) {
            return implode(',', $value);
        }

        return $value;
    }

    public function setMedicationAttribute($value)
    {
        $this->attributes['medication'] = is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value;
    }

    public function setCnMedicationAttribute($value)
    {
        $this->attributes['cn_medication'] = is_array($value) ? json_encode($value, JSON_UNESCAPED_UNICODE) : $value;
    }

    public function setClinicAtAttribute($value)
    {
        if (('0000-00-00' == $value) || '' === $value) {
            $this->attributes['clinic_at'] = null;
        } else {
            $this->attributes['clinic_at'] = $value;
        }
    }

    public function getClinicAtAttribute($value)
    {
        return is_null($value) ? '' : $value;
    }

    /**
     * Create a new Eloquent Collection instance.
     *
     * @param  array $models
     * @return \Illuminate\Database\Eloquent\Collection
     */
//    public function newCollection(array $models = [])
//    {
//        return new Collection($models);
//    }
}
